package org.example.mydeom.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthUser;
import org.apache.commons.lang3.StringUtils;
import org.example.mydeom.common.MessageConstant;
import org.example.mydeom.common.RedisConstant;
import org.example.mydeom.exception.PasswordRepeatException;
import org.example.mydeom.exception.UserHasFoundException;
import org.example.mydeom.exception.UserNotFoundException;
import org.example.mydeom.exception.UsernamePasswordNotFoundException;
import org.example.mydeom.mapper.RoleMapper;
import org.example.mydeom.pojo.dto.UserLoginDTO;
import org.example.mydeom.pojo.dto.UserRegisterDTO;
import org.example.mydeom.pojo.entity.Role;
import org.example.mydeom.pojo.entity.User;
import org.example.mydeom.mapper.UserMapper;
import org.example.mydeom.pojo.vo.UserVO;
import org.example.mydeom.result.Result;
import org.example.mydeom.service.UserService;
import org.example.mydeom.util.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = lambdaQuery().eq(User::getUsername, username).one();
        //User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
        if(user == null){
            throw new UserNotFoundException(MessageConstant.USER_NOT_FOUND);//用户不存在
        }
        if(user.getUsername().equals("admin")){
            user.setAuthorities(List.of(new SimpleGrantedAuthority("ROLE_ADMIN")));
        }else{
            setAurhorities(user);
        }
        return user;
    }

    private void setAurhorities(User user) {
        List<Role> roles= roleMapper.getByUserId(user.getId());
        List<SimpleGrantedAuthority> authorities = roles.stream()
                .map(role -> new SimpleGrantedAuthority("ROLE_"+role.getRoleCode().toUpperCase()))
                .collect(Collectors.toList());
        user.setAuthorities(authorities);
    }
    @Override
    public Result<UserVO> login(UserLoginDTO userLoginDTO, AuthenticationManager authenticationManager) {
        if(StringUtils.isBlank(userLoginDTO.getUsername())||StringUtils.isBlank(userLoginDTO.getPassword())){
            throw new UsernamePasswordNotFoundException(MessageConstant.USERNAME_PASSWORD_NOT_NULL);
        }
        Authentication authentication= authenticationManager.
                authenticate(new UsernamePasswordAuthenticationToken(
                        userLoginDTO.getUsername(),
                        userLoginDTO.getPassword()
                        )
                );
        User user = (User)authentication.getPrincipal();//获取用户信息
        //user.setAuthorities(user.getAuthorities());
        String jwt = JwtTokenUtil.generateJwtToken(user);//生成jwt令牌
        //String jwt = JwtUtilT.createJwt(user);
        //将jwt令牌保存到redis中
        redisTemplate.opsForValue().set(RedisConstant.USER_TOKEN+user.getId(),jwt,JwtTokenUtil.JWT_TTL, TimeUnit.MILLISECONDS);
        //存储用户信息
        SecurityContextHolder.getContext().setAuthentication(authentication);
        log.info("jwt:{}",jwt);
        UserVO userVO = new UserVO(user.getId(), user.getUsername(), jwt);
        return Result.success(userVO);
    }

    @Override
    public Result<Void> register(UserRegisterDTO userRegisterDTO, PasswordEncoder passwordEncoder) {
        if (!StringUtils.isNotBlank(userRegisterDTO.getUsername()) ||
                !StringUtils.isNotBlank(userRegisterDTO.getPassword()) ||
                !StringUtils.isNotBlank(userRegisterDTO.getConfirmPassword())) {
            throw new UsernamePasswordNotFoundException(MessageConstant.USERNAME_PASSWORD_NOT_NULL);
        }
        // 密码一致性校验
        if (!userRegisterDTO.getPassword().equals(userRegisterDTO.getConfirmPassword())) {
            throw new PasswordRepeatException(MessageConstant.PASSWORD_NOT_REPEAT);
        }
        User user = lambdaQuery().eq(User::getUsername, userRegisterDTO.getUsername()).one();
        if(user != null){
            throw new UserHasFoundException(MessageConstant.USER_HAS_FOUND);
        }
        User newUser = new User();
        newUser.setUsername(userRegisterDTO.getUsername());
        newUser.setPassword(passwordEncoder.encode(userRegisterDTO.getPassword()));
        newUser.setCreateTime(LocalDateTime.now());
        newUser.setUpdateTime(LocalDateTime.now());
        save(newUser);
        return Result.success();
    }

    @Override
    public Result<UserVO> otherLogin(AuthUser data, PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager) {
        String username = data.getUsername();
        User user = lambdaQuery().eq(User::getUsername, username).one();
        //用户不存在,注册用户
        if(user == null){
            User newUser = new User();
            newUser.setUsername(username);
            newUser.setPassword(passwordEncoder.encode("123456"));
            newUser.setCreateTime(LocalDateTime.now());
            newUser.setUpdateTime(LocalDateTime.now());
            save(newUser);
            user = lambdaQuery().eq(User::getUsername, username).one();
        }
        // 获取用户权限
        setAurhorities(user);
        //存储用户信息
        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
                user.getUsername(),
                user.getPassword(),
                user.getAuthorities()
        ));
        String jwt = JwtTokenUtil.generateJwtToken(user);
        log.info("jwt:{}",jwt);
        redisTemplate.opsForValue().set(RedisConstant.USER_TOKEN+user.getId(),jwt,JwtTokenUtil.JWT_TTL, TimeUnit.MILLISECONDS);
        return Result.success(new UserVO(user.getId(), user.getUsername(), jwt));
    }


}
